"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var types_1 = require("./types");
var util_1 = require("./util");
var lodash_1 = __importDefault(require("lodash"));
var not_1 = require("./not");
/**
 * 笛卡尔展开多个集合
 *
 * @param {string[][][]} idMatrix - 集合的集合
 * @return {string[][]} 展开后的集合
 */
function decareCollection(idMatrix) {
    if (idMatrix.length === 0) {
        return [];
    }
    if (idMatrix.length === 1) {
        return idMatrix[0];
    }
    var prefixList = idMatrix.shift();
    var suffixList = decareCollection(idMatrix);
    var rst = [];
    prefixList.forEach(function (prefix) {
        suffixList.forEach(function (sufix) {
            rst.push(__spreadArrays(prefix, sufix));
        });
    });
    return rst;
}
exports.decareCollection = decareCollection;
function expandImp(exp, prefix) {
    if (util_1.isBoolExpression(exp)) {
        prefix = prefix || [];
        if (exp.operator === types_1.BoolOperation.AND) {
            // 叉乘
            var suffixMatrix = exp.args.map(function (item) { return expandImp(item); });
            var suffixDecare = decareCollection(suffixMatrix);
            if (prefix && prefix.length > 0) {
                return decareCollection([prefix, suffixDecare]);
            }
            return suffixDecare;
        }
        else {
            // OR
            var suffixMatrix = exp.args.map(function (item) { return expandImp(item, prefix); });
            return Array.prototype.concat.apply([], suffixMatrix);
        }
    }
    else {
        if (prefix && prefix.length > 0) {
            return prefix.map(function (pre) { return __spreadArrays(pre, [exp.uuid]); });
        }
        else {
            return [[exp.uuid]];
        }
    }
}
function intersection$(expA, expB) {
    var _a;
    var clone = lodash_1.default.cloneDeep;
    // key不同的，交集未空集
    if (expA.key !== expB.key) {
        return types_1.EMPTY;
    }
    if (expA.operator > expB.operator) {
        _a = [expA, expB], expB = _a[0], expA = _a[1];
    }
    var opA = expA.operator, vA = expA.value;
    var opB = expB.operator, vB = expB.value;
    // 任意集合和全集的交集是原集合
    if (opB === types_1.Operator.FULL) {
        return expA;
    }
    // 任意集合和空集的交集是空集
    if (opA === types_1.Operator.EMPTY || opB === types_1.Operator.EMPTY) {
        return types_1.EMPTY;
    }
    if (opA === types_1.Operator.SEGMENTS_INNER) {
        if (Array.isArray(vA)) {
            var values = vA.map(function (item) { return intersectionItem(item, expB); });
            var composed_1 = [];
            values.forEach(function (item) {
                if (item.operator === types_1.Operator.EMPTY) {
                    return;
                }
                if (item.operator === types_1.Operator.SEGMENTS_INNER) {
                    composed_1.push.apply(composed_1, item.value);
                }
                else {
                    composed_1.push(item);
                }
            });
            return {
                key: expA.key,
                operator: types_1.Operator.SEGMENTS_INNER,
                value: composed_1,
            };
        }
        else {
            return types_1.EMPTY;
        }
    }
    if (opB === types_1.Operator.SEGMENTS_INNER) {
        if (Array.isArray(vB)) {
            var values = vB.map(function (item) { return intersectionItem(expA, item); });
            var composed_2 = [];
            values.forEach(function (item) {
                if (item.operator === types_1.Operator.EMPTY) {
                    return;
                }
                if (item.operator === types_1.Operator.SEGMENTS_INNER) {
                    composed_2.push.apply(composed_2, item.value);
                }
                else {
                    composed_2.push(item);
                }
            });
            return {
                key: expA.key,
                operator: types_1.Operator.SEGMENTS_INNER,
                value: composed_2,
            };
        }
        else {
            return types_1.EMPTY;
        }
    }
    if (opA === types_1.Operator.EQ) {
        switch (opB) {
            case types_1.Operator.EQ:
                return vA === vB ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.GT:
                return vA > vB ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.LT:
                return vA < vB ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.NGT:
                return vA <= vB ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.NLT:
                return vA >= vB ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.NEQ:
                return vA !== vB ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.IN:
                return Array.isArray(vB) && vB.includes(vA) ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.NOT_IN:
                return Array.isArray(vB) && !vB.includes(vA) ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.RIN:
                return Array.isArray(vB) && vB.length > 1 && vA <= vB[1] && vA >= vB[0]
                    ? clone(expA)
                    : types_1.EMPTY;
            case types_1.Operator.LO_IN_INNER:
                return Array.isArray(vB) && vB.length > 1 && vA <= vB[1] && vA > vB[0] ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.RO_IN_INNER:
                return Array.isArray(vB) && vB.length > 1 && vA < vB[1] && vA >= vB[0] ? clone(expA) : types_1.EMPTY;
            case types_1.Operator.O_IN_INNER:
                return Array.isArray(vB) && vB.length > 1 && vA < vB[1] && vA > vB[0] ? clone(expA) : types_1.EMPTY;
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.NEQ) {
        switch (opB) {
            case types_1.Operator.NEQ:
                if (vA === vB) {
                    return clone(expA);
                }
                else {
                    var min = Math.min(vA, vB);
                    var max = Math.max(vA, vB);
                    return {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: [
                            {
                                key: expA.key,
                                operator: types_1.Operator.LT,
                                value: min,
                            },
                            {
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [min, max],
                            },
                            {
                                key: expA.key,
                                operator: types_1.Operator.GT,
                                value: max,
                            },
                        ],
                    };
                }
            case types_1.Operator.IN:
                if (Array.isArray(vB)) {
                    if (vB.includes(vA)) {
                        var rst = clone(expB);
                        var vr = rst.value;
                        vr.splice(vr.indexOf(vA), 1);
                        if (vr.length === 0) {
                            return types_1.EMPTY;
                        }
                        return rst;
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.NOT_IN:
                if (!Array.isArray(vB)) {
                    return types_1.EMPTY;
                }
                {
                    var rst = clone(expB);
                    var rstV = clone(expB.value);
                    rstV.push(vA);
                    rst.value = lodash_1.default.sortBy(lodash_1.default.uniq(rstV));
                    return rst;
                }
            case types_1.Operator.LT:
                if (vA >= vB) {
                    return clone(expB);
                }
                else {
                    var rst = {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: [
                            {
                                key: expA.key,
                                operator: types_1.Operator.LT,
                                value: vA,
                            },
                            {
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [vA, vB],
                            },
                        ],
                    };
                    return rst;
                }
            case types_1.Operator.GT:
                if (vA <= vB) {
                    return clone(expB);
                }
                else {
                    var rst = {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: [
                            {
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [vB, vA],
                            },
                            {
                                key: expA.key,
                                operator: types_1.Operator.GT,
                                value: vA,
                            },
                        ],
                    };
                    return rst;
                }
            case types_1.Operator.NGT:
                if (vA > vB) {
                    return clone(expB);
                }
                else if (vA === vB) {
                    var rst = clone(expB);
                    rst.operator = types_1.Operator.LT;
                    return rst;
                }
                else {
                    var rst = {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: [
                            {
                                key: expA.key,
                                operator: types_1.Operator.LT,
                                value: vA,
                            },
                            {
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [vA, vB],
                            },
                        ],
                    };
                    return rst;
                }
            case types_1.Operator.NLT:
                if (vA < vB) {
                    return clone(expB);
                }
                else if (vA === vB) {
                    var rst = clone(expB);
                    rst.operator = types_1.Operator.GT;
                    return rst;
                }
                else {
                    var rst = {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: [
                            {
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [vB, vA],
                            },
                            {
                                key: expA.key,
                                operator: types_1.Operator.GT,
                                value: vA,
                            },
                        ],
                    };
                    return rst;
                }
            case types_1.Operator.RIN:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left || vA > vB) {
                        return clone(expB);
                    }
                    else if (vA === left) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.LO_IN_INNER;
                        return rst;
                    }
                    else if (vA === right) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.RO_IN_INNER;
                        return rst;
                    }
                    else {
                        var rst = {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: [
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.RO_IN_INNER,
                                    value: [left, vA],
                                },
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.LO_IN_INNER,
                                    value: [vA, right],
                                },
                            ],
                        };
                        return rst;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left || vA > vB) {
                        return clone(expB);
                    }
                    else if (vA === left) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.LO_IN_INNER;
                        return rst;
                    }
                    else if (vA === right) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.RO_IN_INNER;
                        return rst;
                    }
                    else {
                        var rst = {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: [
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.O_IN_INNER,
                                    value: [left, vA],
                                },
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.LO_IN_INNER,
                                    value: [vA, right],
                                },
                            ],
                        };
                        return rst;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.RO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left || vA >= vB) {
                        return clone(expB);
                    }
                    else if (vA === left) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.LO_IN_INNER;
                        return rst;
                    }
                    else if (vA === right) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.RO_IN_INNER;
                        return rst;
                    }
                    else {
                        var rst = {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: [
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.RO_IN_INNER,
                                    value: [left, vA],
                                },
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.O_IN_INNER,
                                    value: [vA, right],
                                },
                            ],
                        };
                        return rst;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.O_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left || vA >= vB) {
                        return clone(expB);
                    }
                    else if (vA === left || vA === right) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.O_IN_INNER;
                        return rst;
                    }
                    else {
                        var rst = {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: [
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.O_IN_INNER,
                                    value: [left, vA],
                                },
                                {
                                    key: expA.key,
                                    operator: types_1.Operator.O_IN_INNER,
                                    value: [vA, right],
                                },
                            ],
                        };
                        return rst;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.IN) {
        if (!Array.isArray(vA)) {
            return types_1.EMPTY;
        }
        switch (opB) {
            case types_1.Operator.IN:
                if (Array.isArray(vB)) {
                    var rst = clone(expA);
                    rst.value = lodash_1.default.intersection(vA, vB);
                    if (rst.value.length === 0) {
                        return types_1.EMPTY;
                    }
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.NOT_IN:
                if (Array.isArray(vB)) {
                    var rst = clone(expA);
                    rst.value = lodash_1.default.difference(vA, vB);
                    if (rst.value.length === 0) {
                        return types_1.EMPTY;
                    }
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LT: {
                var rst = clone(expA);
                rst.value = vA.filter(function (i) { return i < vB; });
                if (rst.value.length === 0) {
                    return types_1.EMPTY;
                }
                return rst;
            }
            case types_1.Operator.GT: {
                var rst = clone(expA);
                rst.value = vA.filter(function (i) { return i > vB; });
                if (rst.value.length === 0) {
                    return types_1.EMPTY;
                }
                return rst;
            }
            case types_1.Operator.NGT: {
                var rst = clone(expA);
                rst.value = vA.filter(function (i) { return i <= vB; });
                if (rst.value.length === 0) {
                    return types_1.EMPTY;
                }
                return rst;
            }
            case types_1.Operator.NLT: {
                var rst = clone(expA);
                rst.value = vA.filter(function (i) { return i >= vB; });
                if (rst.value.length === 0) {
                    return types_1.EMPTY;
                }
                return rst;
            }
            case types_1.Operator.RIN:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_1 = vB[0], right_1 = vB[1];
                    var rst = clone(expA);
                    rst.value = vA.filter(function (i) { return i >= left_1 && i <= right_1; });
                    if (rst.value.length === 0) {
                        return types_1.EMPTY;
                    }
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_2 = vB[0], right_2 = vB[1];
                    var rst = clone(expA);
                    rst.value = vA.filter(function (i) { return i > left_2 && i <= right_2; });
                    if (rst.value.length === 0) {
                        return types_1.EMPTY;
                    }
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.RO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_3 = vB[0], right_3 = vB[1];
                    var rst = clone(expA);
                    rst.value = vA.filter(function (i) { return i >= left_3 && i < right_3; });
                    if (rst.value.length === 0) {
                        return types_1.EMPTY;
                    }
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.O_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_4 = vB[0], right_4 = vB[1];
                    var rst = clone(expA);
                    rst.value = vA.filter(function (i) { return i > left_4 && i < right_4; });
                    if (rst.value.length === 0) {
                        return types_1.EMPTY;
                    }
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.NOT_IN) {
        if (!Array.isArray(vA) || vA.length < 1) {
            return types_1.EMPTY;
        }
        switch (opB) {
            case types_1.Operator.NOT_IN: {
                if (Array.isArray(vB) && vB.length > 0) {
                    var rst = clone(expA);
                    rst.value = lodash_1.default.sortBy(lodash_1.default.union(vA, vB));
                    return rst;
                }
                else {
                    return types_1.EMPTY;
                }
            }
            case types_1.Operator.LT: {
                var min = Math.min.apply(Math, vA);
                // const max = Math.max(...(vA as number[]));
                if (vB <= min) {
                    return clone(expB);
                }
                else {
                    var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i <= vB; }));
                    var rstValues_1 = [];
                    var lastPort_1 = null;
                    segPart.forEach(function (point) {
                        if (lastPort_1 == null) {
                            rstValues_1.push({
                                key: expA.key,
                                operator: types_1.Operator.LT,
                                value: point,
                            });
                        }
                        else {
                            rstValues_1.push({
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [lastPort_1, point],
                            });
                        }
                        lastPort_1 = point;
                    });
                    if (lastPort_1 !== null && lastPort_1 < vB) {
                        rstValues_1.push({
                            key: expA.key,
                            operator: types_1.Operator.O_IN_INNER,
                            value: [lastPort_1, vB],
                        });
                    }
                    return {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: rstValues_1,
                    };
                }
            }
            case types_1.Operator.GT: {
                var max = Math.max.apply(Math, vA);
                if (vB >= max) {
                    return clone(expB);
                }
                else {
                    var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i > vB; }));
                    var rstValues_2 = [];
                    var lastPort_2 = vB;
                    segPart.forEach(function (point) {
                        rstValues_2.push({
                            key: expA.key,
                            operator: types_1.Operator.O_IN_INNER,
                            value: [lastPort_2, point],
                        });
                        lastPort_2 = point;
                    });
                    rstValues_2.push({
                        key: expA.key,
                        operator: types_1.Operator.GT,
                        value: lastPort_2,
                    });
                    return {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: rstValues_2,
                    };
                }
            }
            case types_1.Operator.NGT: {
                var min = Math.min.apply(Math, vA);
                if (vB < min) {
                    return clone(expB);
                }
                else if (vB === min) {
                    var rst = clone(expB);
                    rst.operator = types_1.Operator.LT;
                    return rst;
                }
                else {
                    var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i <= vB; }));
                    var rstValues_3 = [];
                    var lastPort_3 = null;
                    segPart.forEach(function (point) {
                        if (lastPort_3 == null) {
                            rstValues_3.push({
                                key: expA.key,
                                operator: types_1.Operator.LT,
                                value: point,
                            });
                        }
                        else {
                            rstValues_3.push({
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [lastPort_3, point],
                            });
                        }
                        lastPort_3 = point;
                    });
                    if (lastPort_3 !== null && lastPort_3 < vB) {
                        rstValues_3.push({
                            key: expA.key,
                            operator: types_1.Operator.LO_IN_INNER,
                            value: [lastPort_3, vB],
                        });
                    }
                    return {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: rstValues_3,
                    };
                }
            }
            case types_1.Operator.NLT: {
                var max = Math.max.apply(Math, vA);
                if (vB > max) {
                    return clone(expB);
                }
                else if (vB === max) {
                    var rst = clone(expB);
                    rst.operator = types_1.Operator.GT;
                    return rst;
                }
                else {
                    var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i >= vB; }));
                    var rstValues_4 = [];
                    var lastPort_4 = vB;
                    var closeLeftEnding_1 = lastPort_4 !== segPart[0];
                    segPart.forEach(function (point) {
                        if (point > lastPort_4) {
                            rstValues_4.push({
                                key: expA.key,
                                operator: closeLeftEnding_1 ? types_1.Operator.RO_IN_INNER : types_1.Operator.O_IN_INNER,
                                value: [lastPort_4, point],
                            });
                            closeLeftEnding_1 = false;
                        }
                        lastPort_4 = point;
                    });
                    rstValues_4.push({
                        key: expA.key,
                        operator: types_1.Operator.GT,
                        value: lastPort_4,
                    });
                    return {
                        key: expA.key,
                        operator: types_1.Operator.SEGMENTS_INNER,
                        value: rstValues_4,
                    };
                }
            }
            case types_1.Operator.RIN: {
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_5 = vB[0], right_5 = vB[1];
                    var min = Math.min.apply(Math, vA);
                    var max = Math.max.apply(Math, vA);
                    if (right_5 < min || left_5 > max) {
                        return clone(expB);
                    }
                    else if (right_5 === min) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.RO_IN_INNER;
                        return rst;
                    }
                    else if (left_5 === max) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.LO_IN_INNER;
                        return rst;
                    }
                    else {
                        var segPart = lodash_1.default.sortBy(vA
                            .filter(function (i) { return i >= left_5 && i <= right_5; }));
                        var rstValues_5 = [];
                        var lastPort_5 = left_5;
                        var closeLeftEnding_2 = lastPort_5 !== segPart[0];
                        segPart.forEach(function (point) {
                            if (point > left_5) {
                                rstValues_5.push({
                                    key: expA.key,
                                    operator: closeLeftEnding_2 ? types_1.Operator.RO_IN_INNER : types_1.Operator.O_IN_INNER,
                                    value: [lastPort_5, point],
                                });
                                closeLeftEnding_2 = false;
                            }
                            lastPort_5 = point;
                        });
                        if (lastPort_5 < right_5) {
                            rstValues_5.push({
                                key: expA.key,
                                operator: types_1.Operator.LO_IN_INNER,
                                value: [lastPort_5, right_5],
                            });
                        }
                        if (rstValues_5.length === 1) {
                            return rstValues_5[0];
                        }
                        return {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: rstValues_5,
                        };
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            }
            case types_1.Operator.LO_IN_INNER: {
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_6 = vB[0], right_6 = vB[1];
                    var min = Math.min.apply(Math, vA);
                    var max = Math.max.apply(Math, vA);
                    if (right_6 < min || left_6 >= max) {
                        return clone(expB);
                    }
                    else if (right_6 === min) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.O_IN_INNER;
                        return rst;
                    }
                    else {
                        var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i > left_6 && i <= right_6; }));
                        var rstValues_6 = [];
                        var lastPort_6 = left_6;
                        segPart.forEach(function (point) {
                            rstValues_6.push({
                                key: expA.key,
                                operator: types_1.Operator.O_IN_INNER,
                                value: [lastPort_6, point],
                            });
                            lastPort_6 = point;
                        });
                        if (lastPort_6 < right_6) {
                            rstValues_6.push({
                                key: expA.key,
                                operator: types_1.Operator.LO_IN_INNER,
                                value: [lastPort_6, right_6],
                            });
                        }
                        if (rstValues_6.length === 1) {
                            return rstValues_6[0];
                        }
                        return {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: rstValues_6,
                        };
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            }
            case types_1.Operator.RO_IN_INNER: {
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_7 = vB[0], right_7 = vB[1];
                    var min = Math.min.apply(Math, vA);
                    var max = Math.max.apply(Math, vA);
                    if (right_7 <= min || left_7 > max) {
                        return clone(expB);
                    }
                    else if (left_7 === max) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.O_IN_INNER;
                        return rst;
                    }
                    else {
                        var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i >= left_7 && i < right_7; }));
                        var rstValues_7 = [];
                        var lastPort_7 = left_7;
                        var closeLeftEnding_3 = lastPort_7 !== segPart[0];
                        segPart.forEach(function (point) {
                            if (point > left_7) {
                                rstValues_7.push({
                                    key: expA.key,
                                    operator: closeLeftEnding_3 ? types_1.Operator.RO_IN_INNER : types_1.Operator.O_IN_INNER,
                                    value: [lastPort_7, point],
                                });
                                closeLeftEnding_3 = false;
                            }
                            lastPort_7 = point;
                        });
                        rstValues_7.push({
                            key: expA.key,
                            operator: closeLeftEnding_3 ? types_1.Operator.RO_IN_INNER : types_1.Operator.O_IN_INNER,
                            value: [lastPort_7, right_7],
                        });
                        if (rstValues_7.length === 1) {
                            return rstValues_7[0];
                        }
                        return {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: rstValues_7,
                        };
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            }
            case types_1.Operator.O_IN_INNER: {
                if (Array.isArray(vB) && vB.length > 1) {
                    var left_8 = vB[0], right_8 = vB[1];
                    var min = Math.min.apply(Math, vA);
                    var max = Math.max.apply(Math, vA);
                    if (right_8 <= min || left_8 >= max) {
                        return clone(expB);
                    }
                    else {
                        var segPart = lodash_1.default.sortBy(vA.filter(function (i) { return i > left_8 && i < right_8; }));
                        var rstValues_8 = [];
                        var lastPort_8 = left_8;
                        segPart.forEach(function (point) {
                            if (point > left_8) {
                                rstValues_8.push({
                                    key: expA.key,
                                    operator: types_1.Operator.O_IN_INNER,
                                    value: [lastPort_8, point],
                                });
                            }
                            lastPort_8 = point;
                        });
                        rstValues_8.push({
                            key: expA.key,
                            operator: types_1.Operator.O_IN_INNER,
                            value: [lastPort_8, right_8],
                        });
                        if (rstValues_8.length === 1) {
                            return rstValues_8[0];
                        }
                        return {
                            key: expA.key,
                            operator: types_1.Operator.SEGMENTS_INNER,
                            value: rstValues_8,
                        };
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.LT) {
        switch (opB) {
            case types_1.Operator.LT:
                return vA < vB ? clone(expA) : clone(expB);
            case types_1.Operator.GT:
                if (vA <= vB) {
                    return types_1.EMPTY;
                }
                else {
                    return {
                        operator: types_1.Operator.O_IN_INNER,
                        key: expA.key,
                        value: [vB, vA],
                    };
                }
            case types_1.Operator.NGT:
                return vA <= vB ? clone(expA) : clone(expB);
            case types_1.Operator.NLT:
                if (vA <= vB) {
                    return types_1.EMPTY;
                }
                else {
                    return {
                        operator: types_1.Operator.RO_IN_INNER,
                        key: expA.key,
                        value: [vB, vA],
                    };
                }
            case types_1.Operator.RIN:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA <= right) {
                        return {
                            operator: types_1.Operator.RO_IN_INNER,
                            key: expA.key,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.O_IN_INNER,
                            key: expA.key,
                            value: [left, vA],
                        };
                    }
                    else if (vA === right) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.O_IN_INNER;
                        return rst;
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.RO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.RO_IN_INNER,
                            key: expA.key,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.O_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.O_IN_INNER,
                            key: expA.key,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.GT) {
        switch (opB) {
            case types_1.Operator.GT:
                return vA < vB ? clone(expB) : clone(expA);
            case types_1.Operator.NGT:
                if (vA >= vB) {
                    return types_1.EMPTY;
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.LO_IN_INNER,
                        value: [vA, vB],
                    };
                }
            case types_1.Operator.NLT:
                return vA >= vB ? clone(expA) : clone(expB);
            case types_1.Operator.RIN:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left) {
                        return clone(expB);
                    }
                    else if (vA === left) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.LO_IN_INNER;
                        return rst;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.LO_IN_INNER,
                            key: expA.key,
                            value: [vA, right],
                        };
                    }
                    else {
                        return types_1.EMPTY;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left) {
                        return clone(expB);
                    }
                    else if (vA === left) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.O_IN_INNER;
                        return rst;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.LO_IN_INNER,
                            key: expA.key,
                            value: [vA, right],
                        };
                    }
                    else {
                        return types_1.EMPTY;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.RO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left) {
                        return clone(expB);
                    }
                    else if (vA === left) {
                        var rst = clone(expB);
                        rst.operator = types_1.Operator.O_IN_INNER;
                        return rst;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.O_IN_INNER,
                            key: expA.key,
                            value: [vA, right],
                        };
                    }
                    else {
                        return types_1.EMPTY;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.O_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return clone(expB);
                    }
                    else if (vA > left && vA < right) {
                        return {
                            operator: types_1.Operator.O_IN_INNER,
                            key: expA.key,
                            value: [vA, right],
                        };
                    }
                    else {
                        return types_1.EMPTY;
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.NGT) {
        // lt or eq
        switch (opB) {
            case types_1.Operator.NGT:
                return vA <= vB ? clone(expA) : clone(expB);
            case types_1.Operator.NLT:
                if (vA < vB) {
                    return types_1.EMPTY;
                }
                if (vA === vB) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.EQ,
                        value: vA,
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RIN,
                        value: [vB, vA],
                    };
                }
            case types_1.Operator.RIN:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left) {
                        return types_1.EMPTY;
                    }
                    if (vA === left) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.EQ,
                            value: vA,
                        };
                    }
                    else if (vA > left && vA <= right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.RIN,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.LO_IN_INNER,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.RO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA < left) {
                        return types_1.EMPTY;
                    }
                    else if (vA === left) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.EQ,
                            value: vA,
                        };
                    }
                    else if (vA > left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.RIN,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.O_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA <= left) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.O_IN_INNER,
                            value: [left, vA],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.NLT) {
        // gt or eq
        switch (opB) {
            case types_1.Operator.NLT:
                return vA <= vB ? clone(expB) : clone(expA);
            case types_1.Operator.RIN:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA > right) {
                        return types_1.EMPTY;
                    }
                    else if (vA === right) {
                        var rst = clone(expA);
                        rst.operator = types_1.Operator.EQ;
                        return rst;
                    }
                    else if (vA >= left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.RIN,
                            value: [vA, right],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.LO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA > right) {
                        return types_1.EMPTY;
                    }
                    else if (vA === right) {
                        var rst = clone(expA);
                        rst.operator = types_1.Operator.EQ;
                        return rst;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.RIN,
                            value: [vA, right],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.RO_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA >= right) {
                        return types_1.EMPTY;
                    }
                    else if (vA >= left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.RO_IN_INNER,
                            value: [vA, right],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            case types_1.Operator.O_IN_INNER:
                if (Array.isArray(vB) && vB.length > 1) {
                    var left = vB[0], right = vB[1];
                    if (vA >= right) {
                        return types_1.EMPTY;
                    }
                    else if (vA > left && vA < right) {
                        return {
                            key: expA.key,
                            operator: types_1.Operator.RO_IN_INNER,
                            value: [vA, right],
                        };
                    }
                    else {
                        return clone(expB);
                    }
                }
                else {
                    return types_1.EMPTY;
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.RIN) {
        if (!Array.isArray(vA) || vA.length < 2 || !Array.isArray(vB) || vB.length < 2) {
            return types_1.EMPTY;
        }
        var la = vA[0], ra = vA[1];
        var lb = vB[0], rb = vB[1];
        switch (opB) {
            case types_1.Operator.RIN:
                if (ra < lb || la > rb) {
                    return types_1.EMPTY;
                }
                else if (la === rb) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.EQ,
                        value: la,
                    };
                }
                else if (ra === lb) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.EQ,
                        value: ra,
                    };
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RIN,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RIN,
                        value: [la, rb],
                    };
                }
            case types_1.Operator.LO_IN_INNER:
                if (ra <= lb || la > rb) {
                    return types_1.EMPTY;
                }
                if (la === rb) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.EQ,
                        value: la,
                    };
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.LO_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RIN,
                        value: [la, rb],
                    };
                }
            case types_1.Operator.RO_IN_INNER:
                if (ra < lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb === ra) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.EQ,
                        value: lb,
                    };
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RIN,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RO_IN_INNER,
                        value: [la, rb],
                    };
                }
            case types_1.Operator.O_IN_INNER:
                if (ra <= lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la < lb && ra > rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.LO_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RO_IN_INNER,
                        value: [la, rb],
                    };
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.LO_IN_INNER) {
        if (!Array.isArray(vA) || vA.length < 2 || !Array.isArray(vB) || vB.length < 2) {
            return types_1.EMPTY;
        }
        var la = vA[0], ra = vA[1];
        var lb = vB[0], rb = vB[1];
        switch (opB) {
            case types_1.Operator.LO_IN_INNER:
                if (ra <= lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.LO_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.LO_IN_INNER,
                        value: [la, rb],
                    };
                }
            case types_1.Operator.RO_IN_INNER:
                if (ra < lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (ra === lb) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.EQ,
                        value: ra,
                    };
                }
                else if (la === lb && ra === rb) {
                    var rst = clone(expA);
                    rst.operator = types_1.Operator.O_IN_INNER;
                    return rst;
                }
                else if (la < lb && ra > rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RIN,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.O_IN_INNER,
                        value: [la, rb],
                    };
                }
            case types_1.Operator.O_IN_INNER:
                if (ra <= lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.LO_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.O_IN_INNER,
                        value: [la, rb],
                    };
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.RO_IN_INNER) {
        if (!Array.isArray(vA) || vA.length < 2 || !Array.isArray(vB) || vB.length < 2) {
            return types_1.EMPTY;
        }
        var la = vA[0], ra = vA[1];
        var lb = vB[0], rb = vB[1];
        switch (opB) {
            case types_1.Operator.RO_IN_INNER:
                if (ra <= lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RO_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RO_IN_INNER,
                        value: [la, rb],
                    };
                }
            case types_1.Operator.O_IN_INNER:
                if (ra <= lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.O_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.RO_IN_INNER,
                        value: [la, rb],
                    };
                }
            default:
                return types_1.EMPTY;
        }
    }
    else if (opA === types_1.Operator.O_IN_INNER) {
        if (!Array.isArray(vA) || vA.length < 2 || !Array.isArray(vB) || vB.length < 2) {
            return types_1.EMPTY;
        }
        var la = vA[0], ra = vA[1];
        var lb = vB[0], rb = vB[1];
        switch (opB) {
            case types_1.Operator.O_IN_INNER:
                if (ra <= lb || la >= rb) {
                    return types_1.EMPTY;
                }
                else if (la <= lb && ra >= rb) {
                    return clone(expB);
                }
                else if (la > lb && ra < rb) {
                    return clone(expA);
                }
                else if (lb > la) {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.O_IN_INNER,
                        value: [lb, ra],
                    };
                }
                else {
                    return {
                        key: expA.key,
                        operator: types_1.Operator.O_IN_INNER,
                        value: [la, rb],
                    };
                }
            default:
                return types_1.EMPTY;
        }
    }
    return types_1.EMPTY;
}
/**
 * 求两个简单Bool表达式的交集
 */
function intersectionItem(expA, expB) {
    var rst = intersection$(expA, expB);
    if (rst !== null) {
        // makeSureUUID(rst, true);
        // 只有一个区间的Operator.SEGMENTS_INNER
        if (rst.operator === types_1.Operator.SEGMENTS_INNER &&
            Array.isArray(rst.value) &&
            rst.value.length === 1) {
            return rst.value[0];
        }
        if (rst.operator === types_1.Operator.IN && Array.isArray(rst.value) && rst.value.length === 1) {
            return __assign(__assign({}, rst), { operator: types_1.Operator.EQ, value: rst.value[0] });
        }
    }
    return rst;
}
exports.intersectionItem = intersectionItem;
/**
 * 简化一个表达式
 *
 * @param {BoolItem[]} exp - 待简化的表达式，表达式都必须是&&关系
 * @return {BoolItem[]} 简化后的表达式
 */
function simplifyBoolList(exp) {
    var mapByKey = new Map();
    for (var idx = 0, len = exp.length; idx < len; idx += 1) {
        var item = exp[idx];
        var key = item.key;
        if (mapByKey.has(key)) {
            var prev = mapByKey.get(key);
            var mergedItem = intersectionItem(prev, item);
            if ((mergedItem === null || mergedItem === void 0 ? void 0 : mergedItem.operator) === types_1.Operator.EMPTY) {
                return [];
            }
            else {
                mapByKey.set(key, mergedItem);
            }
        }
        else {
            mapByKey.set(key, item);
        }
    }
    return Array.from(mapByKey.values());
}
exports.simplifyBoolList = simplifyBoolList;
/**
 * 将一个Bool表达式展开成多个与关系的表达式
 *
 * @param {Expression} exp - 包含Bool逻辑的表达式
 * @return {Expression[]} 展开的表达式
 */
function expand(exp) {
    util_1.makeSureUUID(exp);
    var itemMap = util_1.buildBoolItemMap(exp);
    var validIdTuple = expandImp(exp);
    var rst = validIdTuple
        .map(function (idList) {
        return simplifyBoolList(idList.map(function (id) { return itemMap.get(id); }));
    })
        .filter(function (list) { return list.length > 0; });
    return rst;
}
exports.expand = expand;
function joinBoolItemList(candidate) {
    if (candidate.length === 0) {
        return types_1.EMPTY;
    }
    else if (candidate.length === 1) {
        return candidate[0];
    }
    else {
        return {
            operator: types_1.BoolOperation.AND,
            args: candidate,
        };
    }
}
function simplify(exp) {
    if (util_1.isBoolExpression(exp)) {
        var itemMatrix = expand(exp);
        if (itemMatrix.length === 0) {
            return types_1.EMPTY;
        }
        else if (itemMatrix.length === 1) {
            return joinBoolItemList(itemMatrix[0]);
        }
        else {
            // 用两次取反，避免求交集
            return not_1.reverse({
                operator: types_1.BoolOperation.AND,
                args: itemMatrix
                    .map(joinBoolItemList)
                    .map(function (e) { return not_1.reverse(e); })
                    .filter(function (i) { return i !== null; }),
            });
        }
    }
    return exp;
}
exports.simplify = simplify;
